package eabnp.eflow.server.impl.hb;

import eabnp.basic.property.EPropertyMap;
import eabnp.basic.result.GResult;
import eabnp.basic.result.IResult;
import eabnp.basic.result.SGResult;
import eabnp.basic.result.SimpleResult;
import eabnp.basic.util.ClassUtil;
import eabnp.basic.util.MiscUtil;
import eabnp.basic.util.StringUtil;
import eabnp.basic.util.SystemEnv;
import eabnp.basic.util.array.FixedArray;
import eabnp.eflow.EFlow;
import eabnp.eflow.EFlowConst;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.ActInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.AppInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.FlowInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.OAServerInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.SysInfo;
import eabnp.eflow.info.ctrlinfo.sysctrl.basicinfo.UserInfo;
import eabnp.eflow.misc.UrgentLevel;
import eabnp.eflow.misc.app2eflow.App2EFlowProcess;
import eabnp.eflow.operation.EFlowCommand;
import eabnp.eflow.operation.SetPLMode;
import eabnp.eflow.server.IEFlowServer;
import eabnp.eflow.server.impl.flowxml.parse.IFlowXMLParser;
import eabnp.eflow.server.impl.flowxml.parse.impl.dom4j.ParserByDom4J;
import eabnp.eflow.server.impl.hb.cache.EFlowCache;
import eabnp.eflow.server.impl.hb.cache.FlowInfoCache;
import eabnp.eflow.server.impl.hb.cache.FlowVersionCache;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_BackSide;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Comment;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Maintenance;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Other;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Resend;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Send;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Takeback;
import eabnp.eflow.server.impl.hb.flowengine.EFlowEngineHB_Todo;
import eabnp.eflow.server.impl.hb.imptool.GetInfo;
import eabnp.eflow.server.impl.hb.imptool.GetTreeOrArray;
import eabnp.eflow.server.impl.hb.imptool.OperateAgent;
import eabnp.eflow.server.impl.hb.imptool.OperateCreate;
import eabnp.eflow.server.impl.hb.imptool.OperateDelete;
import eabnp.eflow.server.impl.hb.imptool.OperateMove;
import eabnp.eflow.server.impl.hb.imptool.OperateOther;
import eabnp.eflow.server.impl.hb.imptool.OperateSet;
import eabnp.eflow.server.impl.hb.imptool.OperateSetAuth;
import eabnp.eflow.server.impl.hb.imptool.OperateSetList;
import eabnp.eflow.server.impl.hb.orm.AbsOOUUORMObj;
import eabnp.eflow.server.impl.hb.orm.AbsORMObj;
import eabnp.eflow.server.impl.hb.orm.HAction;
import eabnp.eflow.server.impl.hb.orm.HApp;
import eabnp.eflow.server.impl.hb.orm.HAppObj;
import eabnp.eflow.server.impl.hb.orm.HCommentColumn;
import eabnp.eflow.server.impl.hb.orm.HCommentGroup;
import eabnp.eflow.server.impl.hb.orm.HFlow;
import eabnp.eflow.server.impl.hb.orm.HFlowVersion;
import eabnp.eflow.server.impl.hb.orm.HForm;
import eabnp.eflow.server.impl.hb.orm.HFunGroup;
import eabnp.eflow.server.impl.hb.orm.HGroup;
import eabnp.eflow.server.impl.hb.orm.HOAServer;
import eabnp.eflow.server.impl.hb.orm.HOrg;
import eabnp.eflow.server.impl.hb.orm.HOrgUnit;
import eabnp.eflow.server.impl.hb.orm.HSys;
import eabnp.eflow.server.impl.hb.orm.HSysOOUUProperty;
import eabnp.eflow.server.impl.hb.orm.HUser;
import eabnp.eflow.server.impl.hb.orm.HViewOrgUnit;
import eabnp.eflow.server.impl.hb.orm.IHavePropertyDoc;
import eabnp.eflow.server.login.ILoginValidate;
import eabnp.eflow.server.login.LoginValidateByEFlow;
import eabnp.eflow.session.ESession;
import eabnp.eflow.tag.EFlowElementType;
import eabnp.eflow.tag.EFlowTagType;
import eabnp.eoperation.IECommand;
import eabnp.eoperation.IEOperation;
import eabnp.etag.ETagUtil;
import eabnp.service.elog.ILogger;
import eabnp.service.hbcenter.HBCenter;
import eabnp.service.hbcenter.HBSessionWrapper;
import eabnp.service.hbcenter.HBUtil;
import eabnp.service.hbcenter.IHBCenterClient;
import eabnp.service.hbcenter.MappingTarget;
import eabnp.service.hbcenter.MappingTargetType;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class EFlowServerByHB
  implements IEFlowServer, IHBCenterClient
{
  private static final String PROPERTY_NAME_LOGINIMPL = "LoginImpl";
  private static final String HIBERNATECENTER_CLIENT_NAME = "EFlow";
  private static final String HBM_PATH = "hbmfile";
  private static final String PROPERTY_NAME_UN = "uniqueName";
  private MappingTarget[] targetArray = new MappingTarget[1];

  private SessionFactory sessionFactory = null;

  private ILoginValidate defaultLoginValidate = new LoginValidateByEFlow();
  private ILoginValidate loginValidate = this.defaultLoginValidate;

  private static final EFlowServerByHB instance = new EFlowServerByHB();

  private static IFlowXMLParser flowXMLParser = new ParserByDom4J();

  public static IFlowXMLParser getFlowXMLParser() {
    return flowXMLParser;
  }

  public static IEFlowServer getInstance()
  {
    return instance;
  }

  public ILogger getEFlowLogger() {
    return EFlow.getInstance().getMyLogger();
  }

  private String getClassName(EFlowTagType type) {
    return EFlowHBUtil.getClassName(type);
  }

  private String getClassName(EFlowTagType pType, EFlowTagType lType) {
    return EFlowHBUtil.getClassName(pType, lType);
  }

  private void initSysCache(Session session)
  {
    String qStr = "from " + EFlowHBUtil.getClassName(EFlowTagType.SYS);
    Query query = session.createQuery(qStr);
    Iterator it = query.iterate();
    while (it.hasNext()) {
      HSys sys = (HSys)it.next();
      SysInfo si = sys.toBasicInfo();
      EFlowCache.putSysInfo(si);
    }
  }

  private void initOAServer(Session session)
  {
    String qStr = "from " + HOAServer.class.getName();
    Query query = session.createQuery(qStr);
    Iterator it = query.iterate();
    while (it.hasNext()) {
      HOAServer oaServer = (HOAServer)it.next();
      OAServerInfo info = oaServer.toBasicInfo();

      HOrgUnit ou = oaServer.getOrgUnit();
      if (ou != null)
        EFlowCache.putOAServer(ou.getUniqueName(), info);
      else
        EFlowCache.putOAServer(oaServer.getOrg().getUniqueName(), info);
    }
  }

  private void initAppCache(Session session)
  {
    String qStr = "from " + EFlowHBUtil.getClassName(EFlowTagType.APP);
    Query q = session.createQuery(qStr);
    List list = q.list();

    Iterator it = list.iterator();
    while (it.hasNext()) {
      HApp app = (HApp)it.next();
      AppInfo info = app.toBasicInfo();
      EFlowCache.putAppInfo(info);
    }
  }

  private void initActCache(Session session)
  {
    String qStr = "from " + EFlowHBUtil.getClassName(EFlowTagType.ACT);
    Query q = session.createQuery(qStr);
    List list = q.list();

    Iterator it = list.iterator();
    while (it.hasNext()) {
      HAction act = (HAction)it.next();
      ActInfo info = act.toBasicInfo();
      EFlowCache.putActInfo(info);
    }
  }

  private void initCommentGroupCache(Session session) {
    String qStr = "from " + EFlowHBUtil.getClassName(EFlowTagType.COMMENTGROUP);
    Query q = session.createQuery(qStr);
    List list = q.list();

    Iterator it = list.iterator();
    while (it.hasNext()) {
      HCommentGroup cg = (HCommentGroup)it.next();
      EFlowCache.putCGCfg(cg.toCfgInfo());
    }
  }

  private void initCommentColumnCache(Session session) {
    String qStr = "from " + 
      EFlowHBUtil.getClassName(EFlowTagType.COMMENTCOLUMN);
    Query q = session.createQuery(qStr);
    List list = q.list();

    Iterator it = list.iterator();
    while (it.hasNext()) {
      HCommentColumn cc = (HCommentColumn)it.next();
      EFlowCache.putCommentColumn(cc.toCtrlInfo());
    }
  }

  public static FlowInfoCache resetFlowCache(HFlow flow, FlowInfoCache fCache)
  {
    if (flow.getAppObj() != null)
      fCache.setAppObjUN(flow.getAppObj().getUniqueName());
    if (flow.getMainForm() != null)
      fCache.setMainFormUN(flow.getMainForm().getUniqueName());
    if (flow.getMainCommentGroup() != null) {
      fCache.setMainCGUN(flow.getMainCommentGroup().getUniqueName());
    }

    FlowInfo info = flow.toBasicInfo();
    fCache.setFlowInfo(info);

    if (flow.getDepartmentLevel() == 0)
      fCache.setDepartmentLevel(EFlow.getProperDepartmentLevel(
        flow.getApp().getDepartmentLevel()));
    else {
      fCache.setDepartmentLevel(flow.getDepartmentLevel());
    }
    fCache.setLoaderScope(flow.getLoaderScope());

    return fCache;
  }

  public static FlowInfoCache genFlowCache(HFlow flow)
  {
    IFlowXMLParser parser = getFlowXMLParser();

    FlowInfoCache fCache = new FlowInfoCache();

    if (flow.getAppObj() != null)
      fCache.setAppObjUN(flow.getAppObj().getUniqueName());
    if (flow.getMainForm() != null)
      fCache.setMainFormUN(flow.getMainForm().getUniqueName());
    if (flow.getMainCommentGroup() != null) {
      fCache.setMainCGUN(flow.getMainCommentGroup().getUniqueName());
    }

    FlowInfo info = flow.toBasicInfo();
    fCache.setFlowInfo(info);

    if (flow.getDepartmentLevel() == 0)
      fCache.setDepartmentLevel(EFlow.getProperDepartmentLevel(
        flow.getApp().getDepartmentLevel()));
    else {
      fCache.setDepartmentLevel(flow.getDepartmentLevel());
    }
    fCache.setLoaderScope(flow.getLoaderScope());

    Set set = flow.getVersionSet();
    if (MiscUtil.getCollectionSize(set) > 0) {
      Iterator it = set.iterator();
      while (it.hasNext()) {
        HFlowVersion fv = (HFlowVersion)it.next();
        FlowVersionCache fvCache = new FlowVersionCache();
        fv.resetFlowVersionCache(fvCache, true, parser);
        fCache.putFlowVersionCache(fvCache);
      }
    }

    return fCache;
  }

  private void initFlowCache(Session session)
  {
    String qStr = "from " + EFlowHBUtil.getClassName(EFlowTagType.FLOW);
    Query q = session.createQuery(qStr);
    List list = q.list();

    q = session.createQuery(qStr);
    list = q.list();
    Iterator it = list.iterator();
    while (it.hasNext()) {
      HFlow flow = (HFlow)it.next();
      FlowInfoCache fCache = genFlowCache(flow);
      EFlowCache.getFlowMap().put(flow.getUniqueName(), fCache);
    }
  }

  private void initCache(Session session)
  {
    EFlowCache.clear();

    initSysCache(session);
    initAppCache(session);
    initActCache(session);
    initFlowCache(session);
    initCommentGroupCache(session);
    initCommentColumnCache(session);
    initOAServer(session);
  }

  private IResult initObject(Session session, String objStr)
  {
    if (StringUtil.isNullOrEmptyStr(objStr)) {
      return GResult.newFailureResult("空的初始化对象");
    }

    String errMsg = "初始化" + objStr + "失败";
    String description = StringUtil.getRightString(objStr, ";");
    objStr = StringUtil.getLeftString(objStr, ";");

    String code = EFlowConst.getCodeFromCfgStr(objStr);
    if (StringUtil.isNullOrEmptyStr(code)) {
      return GResult.newFailureResult("代码为空").addErrMsgPreStr(errMsg);
    }

    String name = EFlowConst.getNameFromCfgStr(objStr);
    if (StringUtil.isNullOrEmptyStr(name)) {
      return GResult.newFailureResult("名称为空").addErrMsgPreStr(errMsg);
    }

    String alias = EFlowConst.getAliasFromCfgStr(objStr);
    if (StringUtil.isNullOrEmptyStr(alias)) {
      alias = null;
    }

    int sn = EFlowConst.getSNFromCfgSTr(objStr);

    EFlowTagType type = EFlowTagType.valueOf(ETagUtil.getTypeStr(objStr));
    if (type == null) {
      return GResult.newFailureResult("错误的初始化对象类型").addErrMsgPreStr(errMsg);
    }

    Object pObj = null;
    EFlowTagType pType = null;
    String parentStr = ETagUtil.getParentStr(objStr);
    if (!StringUtil.isNullOrEmptyStr(parentStr)) {
      pType = EFlowTagType.valueOf(ETagUtil.getTypeStr(parentStr));
      if (pType == null) {
        return GResult.newFailureResult("错误的父节点类型").addErrMsgPreStr(errMsg);
      }

      if (!pType.isTagCanBeMyChild(type)) {
        return GResult.newFailureResult("错误的父节点").addErrMsgPreStr(errMsg);
      }

      GResult gr = queryObjByUN(session, getClassName(pType), 
        parentStr);
      if (gr.isFailure()) {
        return gr.addErrMsgPreStr("查找父节点" + parentStr + "失败").addErrMsgPreStr(
          errMsg);
      }

      if (gr.isNullResult()) {
        return gr.addErrMsgPreStr("父节点" + parentStr + "不存在").addErrMsgPreStr(
          errMsg);
      }

      pObj = gr.getResultObject();
      session.refresh(pObj);
    }

    String un = ETagUtil.genUniqueName(type, code, parentStr);
    GResult gr = queryObjByUN(session, getClassName(type), un);
    if (gr.isFailure()) {
      return gr.addErrMsgPreStr("查找对象失败").addErrMsgPreStr(errMsg);
    }

    if (!gr.isNullResult()) {
      return SimpleResult.SUCCESS;
    }

    AbsORMObj obj = EFlowHBUtil.newOrmObject(type);
    obj.setCode(code);
    obj.setName(name);
    obj.setAlias(alias);
    obj.setSequenceNum(sn);
    obj.setDescription(description);

    if (type == EFlowTagType.USER) {
      HUser user = (HUser)obj;
      if (pType == EFlowTagType.O) {
        HOrg org = (HOrg)pObj;
        user.setOrg(org);
        HOrgUnit ou = org.getMyselfOU();
        user.setOrgUnit(ou);
        user.setOrgUnitUN(ou.getUniqueName());
      } else {
        HOrgUnit ou = (HOrgUnit)pObj;
        user.setOrg(ou.getOrg());
        user.setOrgUnit(ou);
        user.setOrgUnitUN(ou.getUniqueName());
      }
      user.resetFullName();
      user.resetUniqueName();
      if (EFlowConst.ROOT_UN.equals(user.getUniqueName()))
        user.setPassword(EFlowConst.ROOT_DEFAULT_PASSWORD);
    }
    else if (type == EFlowTagType.APP) {
      HApp app = (HApp)obj;
      if (pType == EFlowTagType.APP) {
        HApp pApp = (HApp)pObj;
        app.setSys(pApp.getSys());
        app.setOrg(pApp.getOrg());
        app.setParentApp(pApp);
      } else {
        gr = HBUtil.queryUniqueObjByCode_CatchEx(session, 
          getClassName(EFlowTagType.SYS), code);
        if (gr.isFailure()) {
          return gr.addErrMsgPreStr("查找系统" + code + "失败").addErrMsgPreStr(
            errMsg);
        }
        if (gr.isNullResult()) {
          return gr.resetFailureResult("系统" + code + "不存在").addErrMsgPreStr(
            errMsg);
        }

        HSys sys = (HSys)gr.getResultObject();
        HOrg org = (HOrg)pObj;
        app.setSys(sys);
        app.setOrg(org);
      }
    } else if (type == EFlowTagType.O) {
      HOrg org = (HOrg)obj;
      org.setSysOrgFlag(true);
      org.resetFullName();
    } else if (type == EFlowTagType.FUNGROUP) {
      HFunGroup fg = (HFunGroup)obj;
      fg.setApp((HApp)pObj);
    } else if (type == EFlowTagType.GROUP) {
      HGroup g = (HGroup)obj;
      g.setSysGroupFlag(true);
      if (pType == EFlowTagType.O) {
        HOrg org = (HOrg)pObj;
        g.setOrg(org);
      } else {
        HApp pApp = (HApp)pObj;
        g.setApp((HApp)pObj);
        g.setOrg(pApp.getOrg());
      }
    } else if (type == EFlowTagType.OU) {
      HOrgUnit ou = (HOrgUnit)obj;
      HOrg org = (HOrg)pObj;
      ou.setOrg(org);
      ou.resetFullName();
    }

    obj.resetUniqueName();
    gr = HBUtil.saveObject_CacheEx(session, obj);
    if (gr.isFailure()) {
      getEFlowLogger().logErr(HBUtil.rollBackSession(session));
      return gr.addErrMsgPreStr("保存对象失败").addErrMsgPreStr(errMsg);
    }

    if (obj.getType() == EFlowTagType.O) {
      HViewOrgUnit ou = ((HOrg)obj).createMyselfOU();
      gr = HBUtil.saveObject_CacheEx(session, ou);
      if (gr.isFailure()) {
        getEFlowLogger().logErr(HBUtil.rollBackSession(session));
        return gr.addErrMsgPreStr("保存对象失败").addErrMsgPreStr(errMsg);
      }
    }

    return SimpleResult.SUCCESS;
  }

  private void initializeTest(Session session)
  {
  }

  public IResult initialize() {
    String errMsg = "EFlow初始化失败";

    this.sessionFactory = 
      HBCenter.getSessionFactoryByCientName("EFlow");
    if (this.sessionFactory == null) {
      return GResult.newFailureResult("没有得到Hibernate会话工厂").addErrMsgPreStr(
        errMsg);
    }
    EFlowHBUtil.hbSessionFactory = this.sessionFactory;

    GResult gr = HBUtil.openSession_CatchEx(this.sessionFactory);
    if (gr.isFailure()) {
      return gr.addErrMsgPreStr("不能打开Hibernate会话").addErrMsgPreStr(errMsg);
    }
    Session session = (Session)gr.getResultObject();

    FixedArray array = EFlowConst.INIT_EFLOW_OBJECT_ARRAY;
    int n = array.getLength();
    for (int i = 0; i < n; i++) {
      IResult r = initObject(session, array.getString(i));
      if (r.isFailure()) {
        closeSessionAndLogErr(session);
        return r.toGResult().addErrMsgPreStr(errMsg);
      }

    }

    String loginClass = EFlow.getInstance()
      .getProperty("LoginImpl");
    if (StringUtil.isNotNullEmptyStr(loginClass)) {
      gr = ClassUtil.newInstanceOfClass(loginClass);
      if ((gr.isFailure()) || (gr.isNullResult())) {
        closeSessionAndLogErr(session);
        return gr.addErrMsgPreStr("获取登录对象失败");
      }
      Object obj = gr.getResultObject();
      if (!ClassUtil.isInterfaceImplents(obj, ILoginValidate.class)) {
        closeSessionAndLogErr(session);
        return gr.addErrMsgPreStr("获取登录对象失败");
      }
      this.loginValidate = ((ILoginValidate)obj);
    }

    try
    {
      initCache(session);
    } catch (Exception ex) {
      closeSessionAndLogErr(session);
      return GResult.newFailureResult("初始化对象缓存失败", ex).addErrMsgPreStr(errMsg);
    }

    initializeTest(session);

    closeSessionAndLogErr(session);
    return SimpleResult.SUCCESS;
  }

  public IResult getSysCtrlInfo(String userUN, String sysUN) {
    return GetInfo.getSysCtrlInfo(userUN, sysUN);
  }

  public MappingTarget[] getMappingTarget() {
    MappingTarget mt = this.targetArray[0];
    if (mt == null) {
      String str = EFlow.getInstance().getPath() + SystemEnv.FILE_SEPARATOR + 
        "hbmfile";
      mt = new MappingTarget(MappingTargetType.MTYPE_PATH, str);
      this.targetArray[0] = mt;
    }

    return this.targetArray;
  }

  public IResult getOrgByCode(String orgCode) {
    String errMsg = "根据代码获取组织失败";

    if (StringUtil.isNullOrEmptyStr(orgCode)) {
      return GResult.newFailureResult("代码为空").addErrMsgPreStr(errMsg);
    }

    GResult gr = HBUtil.openSession_CatchEx(this.sessionFactory);
    if (gr.isFailure()) {
      return gr.addErrMsgPreStr(errMsg);
    }

    Session session = (Session)gr.getResultObject();
    gr = HBUtil.queryUniqueObjByCode_CatchEx(session, HOrg.class.getName(), 
      orgCode);
    if (gr.isFailure()) {
      gr.addErrMsgPreStr(errMsg);
      EFlow.getInstance().getMyLogger()
        .logErr(HBUtil.rollBackAndClose(session));
      return gr;
    }

    EFlow.getInstance().getMyLogger().logErr(HBUtil.closeSession(session));
    return gr;
  }

  private GResult queryObjByUN(Session session, String className, String uniqueName)
  {
    return HBUtil.queryUniqueObjByProperty_CatchEx(session, className, 
      "uniqueName", uniqueName);
  }

  private void closeSessionAndLogErr(Session s)
  {
    getEFlowLogger().logErr(HBUtil.closeSession(s));
  }

  private IResult setEntityProperty(ESession es, IEOperation op, EFlowTagType type, SetPLMode mode, EPropertyMap pMap)
  {
    String un = op.getParameterString("un");
    String errMsg = "设置“" + un + "”的属性失败";

    GResult gr = HBUtil.openSession_CatchEx(this.sessionFactory);
    if (gr.isFailure()) {
      gr.addErrMsgPreStr(errMsg);
      return gr;
    }
    Session session = (Session)gr.getResultObject();

    gr = queryObjByUN(session, getClassName(type), un);
    if (gr.isFailure()) {
      closeSessionAndLogErr(session);
      return gr.addErrMsgPreStr("查找失败").addErrMsgPreStr(errMsg);
    }
    if (gr.isNullResult()) {
      closeSessionAndLogErr(session);
      return gr.resetFailureResult("该对象不存在").addErrMsgPreStr(errMsg);
    }

    if (!ClassUtil.isInterfaceImplents(gr.getResultObject().getClass(), 
      IHavePropertyDoc.class.getName())) {
      gr.resetFailureResult("对象不支持属性设置").addErrMsgPreStr(errMsg);
    }

    if (ClassUtil.isSameOrSuperClass(gr.getResultObject().getClass(), 
      AbsORMObj.class)) {
      IResult r = EFlowHBUtil.setBasicProperty((AbsORMObj)gr.getResultObject(), 
        pMap);
      if (r.isFailure()) {
        closeSessionAndLogErr(session);
        return r.toGResult().addErrMsgPreStr(errMsg);
      }

    }

    closeSessionAndLogErr(session);
    return SimpleResult.SUCCESS;
  }

  private IResult setSysOOUUProperty(ESession es, String un, String sysUN, SetPLMode mode, EPropertyMap pMap)
  {
    String errMsg = "设置“" + sysUN + "”下“" + un + "”的属性失败";

    EFlowTagType type = EFlowTagType.getTypeFromTagName(un);
    if ((EFlowTagType.USER != type) && (EFlowTagType.PUSER != type) && 
      (EFlowTagType.O != type) && (EFlowTagType.OU != type)) {
      return SGResult.newFailureResult("错误的组织机构或用户形式").addErrMsgPreStr(errMsg);
    }

    GResult gr = HBUtil.openSession_CatchEx(this.sessionFactory);
    if (gr.isFailure()) {
      gr.addErrMsgPreStr(errMsg);
      return gr;
    }
    Session session = (Session)gr.getResultObject();

    gr = queryObjByUN(session, getClassName(EFlowTagType.SYS), sysUN);
    if (gr.isFailure()) {
      closeSessionAndLogErr(session);
      return gr.addErrMsgPreStr("查找系统失败").addErrMsgPreStr(errMsg);
    }
    if (gr.isNullResult()) {
      closeSessionAndLogErr(session);
      return gr.resetFailureResult("系统不存在").addErrMsgPreStr(errMsg);
    }

    HSys sys = (HSys)gr.getResultObject();

    gr = queryObjByUN(session, getClassName(type), un);
    if (gr.isFailure()) {
      closeSessionAndLogErr(session);
      return gr.addErrMsgPreStr("查找对象失败").addErrMsgPreStr(errMsg);
    }
    if (gr.isNullResult()) {
      closeSessionAndLogErr(session);
      return gr.resetFailureResult("对象不存在").addErrMsgPreStr(errMsg);
    }
    Object obj = gr.getResultObject();

    HSysOOUUProperty p = null;
    try {
      StringBuffer sb = new StringBuffer("from " + 
        getClassName(EFlowTagType.SYS, EFlowTagType.USER) + 
        " as obj where obj.typeStr=:type and ");
      Query q = null;
      if (type == EFlowTagType.USER) {
        sb.append("obj.user=:user");
        q = session.createQuery(sb.toString());
        q.setString("type", type.getName());
        q.setEntity("user", obj);
      }
      else if (type == EFlowTagType.O) {
        sb.append("obj.org=:org");
        q = session.createQuery(sb.toString());
        q.setString("type", type.getName());
        q.setEntity("org", obj);
      }
      else if (type == EFlowTagType.OU) {
        sb.append("obj.orgUnit=:orgUnit");
        q = session.createQuery(sb.toString());
        q.setString("type", type.getName());
        q.setEntity("orgUnit", obj);
      }

      p = (HSysOOUUProperty)q.uniqueResult();
    } catch (Exception ex) {
      closeSessionAndLogErr(session);
      return gr.resetFailureResult("查找属性对象失败", ex).addErrMsgPreStr(errMsg);
    }
    if (p == null) {
      p = new HSysOOUUProperty();
      p.setSys(sys);
      p.setOOUU((AbsOOUUORMObj)obj);
    }

    closeSessionAndLogErr(session);

    return SimpleResult.SUCCESS;
  }

  private IResult operateSetProperty(ESession es, IEOperation op)
  {
    String errMsg = "设置属性失败";

    String un = op.getParameterString("un");
    if (StringUtil.isNullOrEmptyStr(un)) {
      return SGResult.newFailureResult("空UN").addErrMsgPreStr(errMsg);
    }

    SetPLMode mode = (SetPLMode)op.getParameter("setMode");
    if (mode == null) {
      return SGResult.newFailureResult("设置模式为空").addErrMsgPreStr(errMsg);
    }
    EPropertyMap pMap = op
      .getParamAsPropertyMap("propertyMap");
    if (((pMap == null) || (pMap.getPropertySize() == 0)) && (
      (mode == SetPLMode.SET) || (mode == SetPLMode.REMOVE))) {
      return SimpleResult.SUCCESS;
    }

    if (!StringUtil.isContains(un, "@")) {
      EFlowTagType type = EFlowTagType.valueOf(ETagUtil.getTypeStr(un));
      if (type == null) {
        return SGResult.newFailureResult("空UN").addErrMsgPreStr(errMsg);
      }
      errMsg = "设置" + un + "属性失败";

      return setEntityProperty(es, op, type, mode, pMap);
    }
    String un1 = StringUtil.getLeftString(un, 
      "@");
    String un2 = StringUtil.getRightString(un, 
      "@");
    if ((StringUtil.isNullOrEmptyStr(un1)) || (StringUtil.isNullOrEmptyStr(un2))) {
      return SGResult.newFailureResult("错误的UN").addErrMsgPreStr(errMsg);
    }

    EFlowTagType type2 = EFlowTagType.getTypeFromTagName(un2);
    if (type2 == EFlowTagType.SYS) {
      return setSysOOUUProperty(es, un1, un2, mode, pMap);
    }

    return SimpleResult.SUCCESS;
  }

  public IResult operate(ESession es, IEOperation operation)
  {
    String errMsg = "EFlow操作失败";

    if (operation == null) {
      return SGResult.newFailureResult("空操作").addErrMsgPreStr(errMsg);
    }

    IECommand command = operation.getCommand();

    if (command == null) {
      return SGResult.newFailureResult("空指令").addErrMsgPreStr(errMsg);
    }
    if (EFlowCommand.CREATE == command) {
      IResult r = OperateCreate.create(es, operation);
      if (r.isFailure()) EFlowHBUtil.getEFlowLogger().logErr(r);
      return r.toSGResult();
    }

    if (EFlowCommand.ADD_PROCESSINFO == command) {
      EFlowElementType type = (EFlowElementType)operation
        .getParameter("eflowElementType");
      IResult r = EFlowEngineHB_Maintenance.create(es, operation, type);
      if (r.isFailure()) EFlowHBUtil.getEFlowLogger().logErr(r);
      return r.toSGResult();
    }

    if (EFlowCommand.DELETE == command) {
      return OperateDelete.delete(es, operation);
    }
    if (EFlowCommand.SET_LIST == command) {
      return OperateSetList.setList(es, operation);
    }
    if (EFlowCommand.SET_AUTH == command) {
      return OperateSetAuth.setAuth(es, operation);
    }

    if (EFlowCommand.SET_PROPERTY == command) {
      return operateSetProperty(es, operation);
    }
    if (EFlowCommand.SET == command) return OperateSet.set(es, operation);

    if (EFlowCommand.MOVE == command) return OperateMove.move(es, operation);

    if (EFlowCommand.SET_FLOWXML == command) {
      return OperateOther.setFlowXML(es, operation);
    }
    if (EFlowCommand.SET_PROCESSINFO == command) {
      EFlowElementType type = (EFlowElementType)operation
        .getParameter("eflowElementType");
      return EFlowEngineHB_Maintenance.set(es, operation, type);
    }

    return SGResult.newFailureResult("不支持的命令：" + command.toString())
      .addErrMsgPreStr(errMsg);
  }

  public GResult getEFlowObject(String uniqueName) {
    String errMsg = "获取对象" + uniqueName + "失败";
    if (StringUtil.isNullOrEmptyStr(uniqueName)) {
      return GResult.newFailureResult("参数为空").addErrMsgPreStr(errMsg);
    }

    EFlowTagType type = EFlowTagType.valueOf(ETagUtil.getTypeStr(uniqueName));
    if (type == null) {
      return GResult.newFailureResult("参数错误").addErrMsgPreStr(errMsg);
    }
    String className = getClassName(type);

    GResult gr = HBUtil.openSession_CatchEx(this.sessionFactory);
    if (gr.isFailure()) {
      return gr.addErrMsgPreStr(errMsg);
    }

    Session session = (Session)gr.getResultObject();
    gr = HBUtil.queryUniqueObjByProperty_CatchEx(session, className, 
      "uniqueName", uniqueName);
    if (gr.isFailure()) {
      return gr.addErrMsgPreStr(errMsg);
    }

    getEFlowLogger().logErr(HBUtil.closeSession(session));
    return gr;
  }

  public IResult launchProcess(ESession es, String flowUN, String appData)
  {
    return EFlowEngineHB_Other.launchProcess(es, flowUN, appData);
  }

  public IResult loginValidate(String userUniqueName, String password, EPropertyMap paraMap)
  {
    if (StringUtil.isNullOrEmptyStr(userUniqueName)) {
      return SGResult.newFailureResult("空的用户组合代码").addErrMsgToIResult("密码验证失败");
    }

    GResult gr = EFlowHBUtil.openHBSession();
    if (gr.isFailure()) {
      return gr.addErrMsgToIResult("验证用户口令失败");
    }

    Session session = (Session)gr.getResultObject();
    HBSessionWrapper sw = new HBSessionWrapper(session, 
      EFlow.getInstance().getMyLogger());

    HUser user = null;
    try {
      user = (HUser)EFlowHBUtil.queryObjByUN(session, EFlowTagType.USER, 
        userUniqueName);
    } catch (Exception ex) {
      gr.resetFailureResult(ex.getMessage(), ex).addErrMsgPreStr("验证用户口令失败");
    }

    if (user == null) {
      gr.resetFailureResult("没有找到用户“" + userUniqueName + "”").addErrMsgPreStr(
        "验证用户口令失败");
    }

    UserInfo userInfo = user.toBasicInfo();
    sw.close();

    if (userUniqueName.endsWith(EFlowConst.ALL_ORG_UN))
      gr = this.defaultLoginValidate.loginValidate(userInfo, password, null);
    else {
      gr = getLoginValidate().loginValidate(userInfo, password, null);
    }

    if (gr.isFailure()) return gr;
    return gr;
  }

  public IResult loginValAndGetUserInfo(String userUN, String password, EPropertyMap paraMap)
  {
    IResult r = loginValidate(userUN, password, paraMap);
    if (r.isFailure()) return r;
    return getInfo(userUN);
  }

  public SGResult getOrgArray() {
    return GetTreeOrArray.getOrgArray();
  }

  public IResult getOrgOUTree(String orgUN, boolean includeMaintenance) {
    return GetTreeOrArray.getOrgOUTree(orgUN, includeMaintenance);
  }

  public SGResult getSysTree(String sysUN)
  {
    return null;
  }

  public IResult getProcessArray(EPropertyMap paraMap) {
    return EFlowEngineHB_Maintenance.getProcessArray(paraMap);
  }

  public IResult getUserArray(EPropertyMap paraMap) {
    return GetTreeOrArray.getUserArray(paraMap);
  }

  public IResult getInfo(String uniqueName) {
    return GetInfo.getInfo(uniqueName);
  }

  public IResult getSysAppTree(String sysUN) {
    return GetTreeOrArray.getSysAppTree(sysUN, false);
  }

  public IResult getSysUserArray(String sysUN) {
    return GetTreeOrArray.getSysUserArray(sysUN);
  }

  public IResult getUserSysArray(String userUN) {
    return GetTreeOrArray.getUserSysArray(userUN);
  }

  public IResult getFlowStepArray(String flowUN, int flowVersion, String stepType)
  {
    return GetTreeOrArray.getFlowStepArray(flowUN, flowVersion, stepType);
  }

  public IResult getSysAppFlowTree(String sysUN) {
    return GetTreeOrArray.getSysAppTree(sysUN, true);
  }

  public IResult getOrgAppTree(String orgUN) {
    return GetTreeOrArray.getOrgAppTree(orgUN, false);
  }

  public IResult getOrgAppFlowTree(String orgUN) {
    return GetTreeOrArray.getOrgAppTree(orgUN, true);
  }

  public IResult getAppTree(String appUN) {
    return GetTreeOrArray.getAppTree(appUN);
  }

  public IResult getOrgGroupTree(String orgUN) {
    return GetTreeOrArray.getOrgGroupTree(orgUN);
  }

  public IResult getProcessSimpleInfo(ESession es, String processId, String infoType)
  {
    return EFlowEngineHB_Other.getProcessSimpleInfo(es, processId, infoType);
  }

  public IResult loadProcess(ESession es, String processId, String userUN, String title, String appData)
  {
    return EFlowEngineHB_Other.loadProcess(es, processId, userUN, title, 
      appData);
  }

  public IResult visitEFlowPostAct(ESession es, String processId, String taskId, String actId, String appData)
  {
    return EFlowEngineHB_Other.visitEFlowPostAct(es, processId, taskId, actId, 
      appData);
  }

  public IResult getAutoSendConfirm(ESession es, String processId, String taskId, String actId, String theOUByApp, String theUserByApp)
  {
    return EFlowEngineHB_Send.getAutoSendConfirm(es, processId, taskId, actId, 
      theOUByApp, theUserByApp);
  }

  public IResult autoSend(ESession es, String processId, String taskId, String actId, String theOUByApp, String theUserByApp, String appData)
  {
    return EFlowEngineHB_Send.autoSend(es, processId, taskId, actId, 
      theOUByApp, theUserByApp, appData);
  }

  public IResult visitEFlowPreAct(ESession es, String processId, String taskId, String actId)
  {
    return EFlowEngineHB_Other.visitEFlowPreAct(es, processId, taskId, actId);
  }

  public IResult genEFlowXMLFile() {
    return GetTreeOrArray.genEFlowXMLFile(null);
  }

  public IResult getSendCtrlInfo(ESession es, String processId, String taskId, String actId, String theOUByApp, String theUserByApp, String appData)
  {
    return EFlowEngineHB_Send.getSendCtrlInfo(es, processId, taskId, actId, 
      theOUByApp, theUserByApp, appData);
  }

  public IResult selSend(ESession es, String processId, String taskId, String sendStr, String appData)
  {
    return EFlowEngineHB_Send.selSend(es, processId, taskId, sendStr, appData);
  }

  public IResult putComment(ESession es, String processId, String taskId, String actId, String actUserUN, String comment, Date commentDate, String appData)
  {
    return EFlowEngineHB_Comment.putComment(es, processId, taskId, actId, 
      actUserUN, comment, commentDate, appData);
  }

  public IResult getCurComment(ESession es, String processId, String taskId, String actId, String actUserUN)
  {
    return EFlowEngineHB_Comment.getCurComment(es, processId, taskId, actId, 
      actUserUN);
  }

  public IResult getFlowXMLFile(String flowUN, int flowVersion) {
    return GetInfo.getFlowXMLFile(flowUN, flowVersion);
  }

  public IResult getProcessRecordInfo(String processId) {
    return EFlowEngineHB_Other.getProcessRecordInfo(processId);
  }

  public IResult getProcessInfo(String id, EFlowElementType rootType, EFlowElementType childrenType)
  {
    return EFlowEngineHB_Maintenance.getProcessInfo(id, rootType, childrenType);
  }

  public IResult autoTakeback(ESession es, String processId, String actId, String appData)
  {
    return EFlowEngineHB_Takeback.autoTakeBack(es, processId, actId, appData);
  }

  public IResult getGobackAutoConfirm(ESession es, String processId, String actIdEx)
  {
    return EFlowEngineHB_Takeback.getGobackAutoConfirm(es, processId, actIdEx);
  }

  public IResult getTakebackSelCtrl(ESession es, String processId, String actIdEx)
  {
    return EFlowEngineHB_Takeback.getTakebackSelCtrl(es, processId, actIdEx);
  }

  public IResult selTakeback(ESession es, String processId, String actIdEx, String userStr, String appData)
  {
    return EFlowEngineHB_Takeback.selTakeback(es, processId, actIdEx, userStr, 
      appData);
  }

  public IResult getResendListCtrl(ESession es, String processId, String actIdEx, String theOUByApp, String theUserByApp, String appData)
  {
    return EFlowEngineHB_Resend.getResendListCtrl(es, processId, actIdEx, 
      theOUByApp, theUserByApp, appData);
  }

  public IResult getUN_NameArray(String prefix, String postfix) {
    return GetTreeOrArray.getUN_NameArray(prefix, postfix);
  }

  public IResult addUserUsualComment(ESession es, String userUN, String sysCode, String comment)
  {
    return OperateSet.addUserUsualComment(es, userUN, sysCode, comment);
  }

  public IResult addUserUsualWord(ESession es, String userUN, String sysCode, String word)
  {
    return OperateSet.addUserUsualWord(es, userUN, sysCode, word);
  }

  public IResult resetUserUsualComment(ESession es, String userUN, String sysCode, String commentArray)
  {
    return OperateSet.resetUserUsualComment(es, userUN, sysCode, commentArray);
  }

  public IResult resetUserUsualWord(ESession es, String userUN, String sysCode, String wordArray)
  {
    return OperateSet.resetUserUsualWord(es, userUN, sysCode, wordArray);
  }

  public IResult getPUtCommentCtrl(ESession es, String processId, String taskId, String actId, String actUserUN)
  {
    return EFlowEngineHB_Comment.getPutCommentCtrl(es, processId, taskId, 
      actId, actUserUN);
  }

  public IResult resend(ESession es, String processId, String sendStr, String appData)
  {
    return EFlowEngineHB_Resend.resend(es, processId, sendStr, appData);
  }

  public IResult goBack(ESession es, String processId, String actId, String appData)
  {
    return EFlowEngineHB_Takeback.goBack(es, processId, actId, appData);
  }

  public IResult setProcessTitle(ESession es, String processId, String title) {
    return EFlowEngineHB_Other.setProcessTitle(es, processId, title);
  }

  public IResult newAgent(ESession es, String sysUN, String agentUserUN, Date beginDate, Date endDate, String desc)
  {
    return OperateAgent.newAgent(es, sysUN, agentUserUN, beginDate, endDate, 
      desc);
  }

  public IResult getTodoLabelList(ESession es, String sysCodeList) {
    return EFlowEngineHB_Todo.getTodoLabelList(es, sysCodeList);
  }

  public IResult getTodoList(ESession es, String sysCodeList, String labelList, int first, int count)
  {
    return EFlowEngineHB_Todo.getTodoList(es, sysCodeList, labelList, first, 
      count);
  }

  public IResult addTodo(ESession es, String processId, String senderCode, String senderName, String userCode, String userName, String label, String tip, String title, String link, String exInfo, UrgentLevel urLevel)
  {
    return EFlowEngineHB_Todo.addTodo(es, processId, senderCode, senderName, 
      userCode, userName, label, tip, title, link, exInfo, urLevel);
  }

  public IResult resetTodoInfo(ESession es, String processId, String title, String link, String exInfo)
  {
    return EFlowEngineHB_Todo.resetTodoInfo(es, processId, title, link, exInfo);
  }

  public IResult delDone(ESession es, String doneIdList) {
    return EFlowEngineHB_Todo.delDone(es, doneIdList);
  }

  public IResult delTodo(ESession es, String todoIdList) {
    return EFlowEngineHB_Todo.delTodo(es, todoIdList);
  }

  public IResult setDone(ESession es, String todoIdList) {
    return EFlowEngineHB_Todo.setDone(es, todoIdList);
  }

  public IResult exportApp(String appUN) {
    return GetInfo.exportApp(appUN);
  }

  public IResult exportOrg(String orgUN) {
    return GetInfo.exportOrg(orgUN);
  }

  public IResult getDoneLabelList(ESession es, String sysCodeList, Date fromDate, Date toDate)
  {
    return EFlowEngineHB_Todo.getDoneLabelList(es, sysCodeList, fromDate, 
      toDate);
  }

  public IResult deleteById(String id, EFlowElementType element) {
    return EFlowEngineHB_Maintenance.deleteById(id, element);
  }

  public IResult setProcessAppData(ESession es, String processId, String appData) {
    return EFlowEngineHB_Other.setProcessAppData(es, processId, appData);
  }

  public IResult getDoneList(ESession es, String sysCodeList, String labelList, Date fromDate, Date toDate, int first, int count)
  {
    return EFlowEngineHB_Todo.getDoneList(es, sysCodeList, labelList, fromDate, 
      toDate, first, count);
  }

  public IResult checkProcess() {
    return EFlowEngineHB_BackSide.checkProcess();
  }

  public IResult checkTaskUptoTime() {
    return EFlowEngineHB_BackSide.checkTaskUptoTime();
  }

  public IResult importAppProcess(App2EFlowProcess appProcess) {
    return EFlowEngineHB_Maintenance.importProcessFromApp(appProcess);
  }

  public static ILoginValidate getLoginValidate() {
    return instance.loginValidate;
  }

  public IResult getBatchSendCtrl(ESession es, String processIdList, String stepCode, String actName, String theOUByApp, String theUserByApp)
  {
    return EFlowEngineHB_Send.getBatchSendCtrl(es, processIdList, stepCode, 
      actName, theOUByApp, theUserByApp);
  }

  public IResult batchSend(ESession es, String processIdList, String stepCode, String actName, String sendStr)
  {
    return EFlowEngineHB_Send.batchSend(es, processIdList, stepCode, actName, 
      sendStr);
  }

  public IResult launchProcessToStep(ESession es, String flowUN, String stepCode, String title, String appData)
  {
    return EFlowEngineHB_Other.launchProcessToStep(es, flowUN, stepCode, title, 
      appData);
  }

  public IResult getUserAgentInfo(ESession es) {
    return OperateAgent.getUserAgentInfo(es);
  }

  public IResult delAgent(ESession es, String agentIdList) {
    return OperateAgent.delAgent(es, agentIdList);
  }

  public IResult setAgent(ESession es, String agentId, String sysUN, String agentUserUN, Date beginDate, Date endDate, String desc)
  {
    return OperateAgent.setAgent(es, agentId, sysUN, agentUserUN, beginDate, 
      endDate, desc);
  }

  public IResult checkTodoDone() {
    return EFlowEngineHB_BackSide.checkTodoDone();
  }

  public IResult genEFlowXMLFile(String orgCodeList) {
    return GetTreeOrArray.genEFlowXMLFile(orgCodeList);
  }
}